using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace PKGames.AssetLoader
{
	public class DownloadRequest : AssetRequest
	{
		private string _tag;

		private Color _tagColor = Color.cyan;

		private string _url;

		private float _bytesDownloaded;

		private long _expectedCrc;

		private HTTPDownloader _downloader;

		private readonly HashSet<IDownloadListener> _listeners = new HashSet<IDownloadListener>();

		private string Tag
		{
			get
			{
				_tag = "[DownloadRequest] ";
				return _tag;
			}
		}

		public DownloadRequest(string localPath, string url, long expectedCrc = 0L)
		{
			_localPath = localPath;
			_url = url;
			_expectedCrc = expectedCrc;
		}

		public void AddListener(IDownloadListener listener)
		{
			_listeners.Add(listener);
		}

		public void AddListerners(DownloadRequest request)
		{
			foreach (IDownloadListener listener in request._listeners)
			{
				_listeners.Add(listener);
			}
		}

		public void RemoveListener(IDownloadListener listener)
		{
			_listeners.Remove(listener);
		}

		public override IEnumerator Execute()
		{
			DeclareStart();
			yield return MonoSingleton<AssetRequestManager>.Instance.StartCoroutine(DownloadAndWriteFile(_url, _localPath));
		}

		public override void Pause()
		{
			base.CurrentState = State.Paused;
			if (_downloader != null)
			{
				_downloader.Pause();
				UnityEngine.Debug.Log(Tag + "Pausing download: " + _url);
			}
		}

		public override void Resume()
		{
			base.CurrentState = State.Executing;
			if (_downloader != null)
			{
				_downloader.Resume();
				UnityEngine.Debug.Log(Tag + "Resuming download: " + _url);
			}
		}

		private IEnumerator DownloadAndWriteFile(string url, string localFilePath)
		{
			UnityEngine.Debug.Log(Tag + "Starting download : " + url);
			_downloader = new HTTPDownloader(url, localFilePath, 4096);
			yield return MonoSingleton<AssetRequestManager>.Instance.StartCoroutine(_downloader.Download(OnDownloadProgress, 1f));
			switch (_downloader.DownloadState)
			{
			case State.Failed:
				DeclareFailure(url);
				break;
			case State.Successful:
				FileHelper.DoNotBackupInCloud(localFilePath);
				if (_expectedCrc != 0 && _downloader.Crc != _expectedCrc)
				{
					DeclareFailure(url);
					FileHelper.DeleteFile(localFilePath);
					UnityEngine.Debug.LogError(Tag + "Corrupted File. URL: " + url + " CRC: " + _downloader.Crc + " Expected CRC: " + _expectedCrc);
				}
				else
				{
					DeclareSuccess();
				}
				break;
			case State.Paused:
				UnityEngine.Debug.Log(Tag + "Download Paused: " + url);
				break;
			}
			if (_downloader.DownloadState != State.Paused)
			{
				OnFinished.Fire(this);
			}
		}

		private void DeclareStart()
		{
			base.CurrentState = State.Executing;
			foreach (IDownloadListener listener in _listeners)
			{
				listener.NotifyStart();
			}
		}

		private void DeclareSuccess()
		{
			base.CurrentState = State.Successful;
			foreach (IDownloadListener listener in _listeners)
			{
				listener.NotifyFinishedSuccess();
			}
		}

		private void DeclareFailure(string url)
		{
			UnityEngine.Debug.LogWarning(Tag + "Download error. Could not download: " + url);
			base.CurrentState = State.Failed;
			foreach (IDownloadListener listener in _listeners)
			{
				listener.NotifyFinishedFailed();
			}
		}

		private void OnDownloadProgress(float progress, int downloadedBytes, int totalBytes)
		{
			foreach (IDownloadListener listener in _listeners)
			{
				listener.NotifyProgress(progress, downloadedBytes, totalBytes);
			}
		}

		public void NotifyProgress()
		{
			foreach (IDownloadListener listener in _listeners)
			{
				listener.NotifyProgress(_downloader.Progress, _downloader.BytesRead, _downloader.TotalBytes);
			}
		}

		public override void Cancel()
		{
			base.CurrentState = State.Failed;
			if (_downloader != null)
			{
				_downloader.Cancel();
			}
		}
	}
}
